import ObjectUtils from "../utils/ObjectUtils.mjs";
import { arrayRandom } from '../utils/Utils.mjs';
import { split_index, prize_info, sum_info } from "../config/dlt-config.mjs";
import DltDataModel from "./DltDataModel.mjs";

/**
 * 订单模型类
 * @version 1.0.2
 */
class DltOrderModel {

	/**
	 * 渲染订单，与上期开奖结果重复的标记颜色
	 * @param {Array} orderList
	 * @param {String} prevDrawResult
	 */
	renderOrderForPrevDrawResult(orderList, prevDrawResult) {
		orderList = orderList ? orderList.filter(item => item.trim().length > 0) : [];
		if (orderList.length == 0 || !prevDrawResult || prevDrawResult.trim().length == 0) {
			return orderList.map(order => {
				return {
					order,
					text: order,
					frontCount: 0,
					backCount: 0,
					totalCount: 0,
					statusText: '-',
					status: 0,
					moneyText: '-',
					money: 0,
					sum: 0,
					diffSum: 0,
				}
			});
		}
		let numStatus = 0,
			numStatusColor = {
				1: 'text-red-400',
				2: 'text-green-600',
				3: 'text-blue-500'
			}
		let arrTemp = [],
			orderArr = [],
			list = [],
			prevResultArr = [
				[],
				[]
			];
		let rowArr = [];
		let sum = 0,
			diffSum = 0;
		if (prevDrawResult) {
			arrTemp = prevDrawResult.trim().split(' ');
			prevResultArr = [arrTemp.slice(0, split_index), arrTemp.slice(split_index)];
		}

		for (let order of orderList) {
			order = order.trim();
			arrTemp = order.split(' ');
			orderArr = [arrTemp.slice(0, split_index), arrTemp.slice(split_index)];
			sum = arrTemp.reduce((a, b) => {
				return parseInt(a) + parseInt(b)
			});
			diffSum = sum - sum_info.all;
			rowArr = [];
			orderArr[0].forEach(num => {
				numStatus = 0;
				if (prevResultArr[0].includes(num)) {
					numStatus += 2;
				}
				if (numStatus > 0) {
					rowArr.push(`<strong class="${numStatusColor[numStatus]}">${num}</strong>`);
				} else {
					rowArr.push(num);
				}
			})
			orderArr[1].forEach(num => {
				numStatus = 0;
				if (prevResultArr[1].includes(num)) {
					numStatus += 2;
				}
				if (numStatus > 0) {
					rowArr.push(`<strong class="${numStatusColor[numStatus]}">${num}</strong>`);
				} else {
					rowArr.push(num);
				}
			})
			list.push({
				order,
				text: rowArr.join(' '),
				frontCount: 0,
				backCount: 0,
				totalCount: 0,
				statusText: '-',
				status: 0,
				moneyText: '-',
				money: 0,
				sum,
				diffSum,
			})
		}

		return list;
	}
	/**
	 * 计算中奖结果并着色
	 * @param {String} drawResult 开奖号码
	 * @param {Array} orderList 订单列表
	 * @param {Boolean} skipLosing 是否过滤未中奖的记录
	 * @param {String} prevDrawResult 上期开奖号码
	 * @returns {Array} 返回着色后的号码、状态、奖金、中奖数量、和值、和差
	 */
	calcOrder(drawResult, orderList, skipLosing = false, prevDrawResult = '') {
		orderList = orderList ? orderList.filter(item => item.trim().length > 0) : [];
		if (orderList.length == 0 || !drawResult || drawResult.trim().length == 0) {
			return this.renderOrderForPrevDrawResult(orderList, prevDrawResult);
		}
		let numStatus = 0,
			numStatusColor = {
				1: 'text-red-400',
				2: 'text-green-600',
				3: 'text-blue-500'
			}
		let arrTemp = [],
			resultArr = [],
			orderArr = [],
			list = [],
			prevResultArr = [
				[],
				[]
			];
		let rowArr = [];
		let frontCount = 0,
			backCount = 0,
			statusText = '',
			status = 0,
			money = 0,
			moneyText = '',
			sum = 0,
			diffSum = 0;
		arrTemp = drawResult.trim().split(' ');
		resultArr = [arrTemp.slice(0, split_index), arrTemp.slice(split_index)];
		if (prevDrawResult) {
			arrTemp = prevDrawResult.trim().split(' ');
			prevResultArr = [arrTemp.slice(0, split_index), arrTemp.slice(split_index)];
		}

		for (let order of orderList) {
			order = order.trim();
			arrTemp = order.split(' ');
			orderArr = [arrTemp.slice(0, split_index), arrTemp.slice(split_index)];
			sum = arrTemp.reduce((a, b) => {
				return parseInt(a) + parseInt(b)
			});
			diffSum = sum - sum_info.all;
			rowArr = [];
			frontCount = 0;
			backCount = 0;
			statusText = '未中奖';
			status = 0;
			moneyText = 0;
			money = 0;
			orderArr[0].forEach(num => {
				numStatus = 0;
				if (resultArr[0].includes(num)) {
					numStatus += 1;
					frontCount++;
				}
				if (prevResultArr[0].includes(num)) {
					numStatus += 2;
				}
				if (numStatus > 0) {
					rowArr.push(`<strong class="${numStatusColor[numStatus]}">${num}</strong>`);
				} else {
					rowArr.push(num);
				}
			})
			orderArr[1].forEach(num => {
				numStatus = 0;
				if (resultArr[1].includes(num)) {
					numStatus += 1;
					backCount++;
				}
				if (prevResultArr[1].includes(num)) {
					numStatus += 2;
				}
				if (numStatus > 0) {
					rowArr.push(`<strong class="${numStatusColor[numStatus]}">${num}</strong>`);
				} else {
					rowArr.push(num);
				}
			})
			if (frontCount > 0 || backCount > 0) {
				for (let prizeItem of prize_info) {
					if (prizeItem.front == frontCount && prizeItem.back == backCount) {
						statusText = prizeItem.text;
						status = prizeItem.value;
						moneyText = prizeItem.moneyText;
						money = prizeItem.money;
					}
				}
			}
			if (skipLosing && money == 0) {
				continue;
			}
			list.push({
				order,
				text: rowArr.join(' '),
				frontCount,
				backCount,
				totalCount: frontCount + backCount,
				statusText,
				status,
				moneyText,
				money,
				sum,
				diffSum,
			})
		}

		return list;
	}

	/**
	 * 获取开奖列表中的最高奖项
	 * @param {Array} drawList
	 */
	getMaxPrize(drawList) {
		let prizeInfo = {
			value: 0,
			text: '未中奖',
			front: 0,
			back: 0,
			money: 0,
			moneyText: '无'
		};
		if (!drawList?.length) {
			return prizeInfo;
		}
		drawList.forEach((item, idx) => {
			if (prizeInfo.value == 0 || (item.status > 0 && (item.status < prizeInfo.value))) {
				prizeInfo = {
					value: item.status,
					text: item.statusText,
					front: item.frontCount,
					back: item.backCount,
					money: item.money,
					moneyText: item.moneyText
				};
			}
		})
		return prizeInfo;
	}


	/**
	 * 二维数组排列组合
	 * @param {Array} dimensionalArr 
	 * @returns 
	 */
	combination(dimensionalArr) {
		const length = dimensionalArr.length;
		if (length >= 2) {
			const length1 = dimensionalArr[0].length;
			const length2 = dimensionalArr[1].length;
			const lengthProd = length1 * length2;
			const temporary = new Array(lengthProd);
			let index = 0;
			for (let i = 0; i < length1; i++) {
				for (let j = 0; j < length2; j++) {
					if (Array.isArray(dimensionalArr[0][i])) {
						temporary[index] = [].concat([...dimensionalArr[0][i], dimensionalArr[1][j]]);
					} else {
						temporary[index] = [].concat([dimensionalArr[0][i], dimensionalArr[1][j]]);
					}
					index++;
				}
			}
			const newArray = new Array(length - 1);
			newArray[0] = temporary;
			for (let j = 2; j < length; j++) {
				newArray[j - 1] = dimensionalArr[j];
			}
			return this.combination(newArray);
		} else {
			if (dimensionalArr[0] && dimensionalArr[0][0] && Array.isArray(dimensionalArr[0][0])) {
				return dimensionalArr[0];
			}
			return dimensionalArr;
		}
	}

	/**
	 * 二维数组排列组合，只保留中奖的组合
	 * @param {Array} dimensionalArr 
	 * @returns 
	 */
	combinationForDrawal(result, dimensionalArr) {
		let data = {
			rowsCount: 0,
			drawalCount: 0,
			bonus: 0,
			bestPrize: '',
			statusValueMin: 10,
			list: [],
		};
		let orderItem = null;

		function combinationFn(dimensionalArr) {
			const length = dimensionalArr.length;
			if (length >= 2) {
				const length1 = dimensionalArr[0].length;
				const length2 = dimensionalArr[1].length;
				const lengthProd = length1 * length2;
				const temporary = new Array(lengthProd);
				let index = 0;
				for (let i = 0; i < length1; i++) {
					for (let j = 0; j < length2; j++) {
						if (Array.isArray(dimensionalArr[0][i])) {
							temporary[index] = [].concat([...dimensionalArr[0][i], dimensionalArr[1][j]]);
							if (temporary[index].length == 7) {
								orderItem = this.calcOrder(result, [temporary[index].join(' ')])[0];
								if (data.statusValueMin < orderItem.status) {
									data.statusValueMin = orderItem.status;
									data.bestPrize = orderItem.status;
								}
								if (orderItem.money > 0) {
									data.bonus += orderItem.money;
									data.drawalCount++;
									data.list.push(orderItem);
								}
								data.rowsCount++;
							}
						} else {
							temporary[index] = [].concat([dimensionalArr[0][i], dimensionalArr[1][j]]);
						}
						index++;
					}
				}
				const newArray = new Array(length - 1);
				newArray[0] = temporary;
				for (let j = 2; j < length; j++) {
					newArray[j - 1] = dimensionalArr[j];
				}
				return combinationFn(newArray);
			} else {
				if (dimensionalArr[0] && dimensionalArr[0][0] && Array.isArray(dimensionalArr[0][0])) {
					return dimensionalArr[0];
				}
				return dimensionalArr;
			}
		}
		combinationFn(dimensionalArr);
		return data;
	}
	/**
	 * 解析订单号码到 7 个号数选号池或前后区选号池
	 * @param {Array} list 订单号码列表
	 * @returns {Array} [[],[],[],[],[],[],[]] 或 [[],[]]
	 */
	ordersToPoolData(list, isCol = true) {
		if (!list || list.length === 0) {
			return isCol ? [
				[],
				[],
				[],
				[],
				[],
				[],
				[]
			] : [
				[],
				[]
			];
		}
		let item = [];
		if (isCol) {
			let data = [
				[],
				[],
				[],
				[],
				[],
				[],
				[]
			];
			list.forEach(line => {
				item = line.replace(/\s{2}/g, ' ').split(' ').filter(v => v.trim().length == 2);
				if (item.length == 7) {
					for (let i in item) {
						if (!data[i].includes(item[i])) {
							data[i].push(item[i]);
						}
					}
				}
			})
			for (let i = 0; i < data.length; i++) {
				data[i] = Array.from(new Set(data[i])).sort();
			}
			return data;
		}
		let frontData = [],
			backData = []
		list.forEach(line => {
			item = line.replace(/\s{2}/g, ' ').split(' ').filter(v => v.trim().length == 2);
			if (item.length == 7) {
				frontData = frontData.concat(item.slice(0, split_index));
				backData = backData.concat(item.slice(split_index));
			}
		})
		return [
			Array.from(new Set(frontData)).sort().map(v => v.slice(-2)),
			Array.from(new Set(backData)).sort().map(v => v.slice(-2)),
		];
	}


	/**
	 * 解析 AI 推荐选号
	 * @param {String} text AI 选号内容
	 * @param {String} provider AI 服务提供商
	 * @returns {Array} 返回号码数组
	 */
	parseAiText(text, provider) {
		let matches = null;
		switch (provider) {
			case 'nami':
				// 解析纳米搜索内容
				// 【示例】
				// 前区 05, 14, 20, 29, 33 | 后区 04, 10
				// 前区：12 15 19 26 31 | 后区：05 12
				// 前区：09, 14, 21, 27, 34
				// 后区：05, 10
				// 逻辑：热号主导（14、20、29近10期高频）+ 冷号回补（05遗漏≥8期），后区1路偶数组合（04、10）5。
				matches = text.match(
					/前区：?\s?(\d{2}(\,?\s?\d{2}){4})\s*\|?\s*后区：?\s?(\d{2}(\,?\s?\d){2})/ig);
				if (matches) {
					// ['前区 05, 14, 20, 29, 33 | 后区 04, 10', '前区 13, 17, 23, 30, 34 | 后区 02, 08', ...]
					return matches.map(v => v.replace(/前区：?\s?|后区：?\s?|\||\,/g, ' ').replace(/\s{2,}/g, ' ')
						.trim());
				}
				//【示例】
				// 1	05,14,20,29,33	04,10	冷热搭配（05冷+33热），后区1路偶数组合6。
				// 2	13,17,23,30,34	02,08	热号（23、30）+冷号回补（13、17）6。
				// 10	09,15,20,27,31	02,11	高频冷热组合（09冷+20热）23。
				matches = text.match(/(\d{2}(,*\s*\d{2}){4})\s*[\+\|]*\s*(\d{2}(,*\s*\d{2}))/ig);
				if (matches) {
					// ['前区 05, 14, 20, 29, 33 | 后区 04, 10', '前区 13, 17, 23, 30, 34 | 后区 02, 08', ...]
					return matches.map(v => v.replace(/\,/g, ' ').replace(/\s+/gi, ' ').trim());
				}
				break;
			case 'deepseek':
				// 解析 DeepSeek 内容
				// 【示例】
				// 第1注：03 11 18 24 32 + 05 09
				// 第2注：07 14 19 27 33 + 02 08
				matches = text.match(/(\d{2}(,*\s*\d{2}){4})\s*\+\s*(\d{2}(,*\s*\d{2}))/ig);
				if (matches) {
					// ['前区 05, 14, 20, 29, 33 | 后区 04, 10', '前区 13, 17, 23, 30, 34 | 后区 02, 08', ...]
					return matches.map(v => v.replace(/\+/g, '').replace(/\s{2,}/g, ' ').trim());
				}
				break;
		}
		return [];
	}

	/**
	 * 机选一注
	 * @param {Object} statDrawal 历史开奖号码统计信息 {statAll, statColumns}
	 * @param {Number} filterLevel 过滤等级
	 * @param {String} prevDrawResult 上期开奖号码
	 * @param {Array} frontData 前区号码池
	 * @param {Array} backData 后区号码池
	 * @param {String} frontAndBackPoolText 前区和后区号码池字符串
	 * @returns 
	 */
	getRandomNums7WithFab(statDrawal, filterLevel = 1, prevDrawResult = '', frontData = null, backData = null,
		frontAndBackPoolText = '') {
		if (!statDrawal) {
			statDrawal = (new DltDataModel()).getDrawalStat();
		}
		if (!frontData || !backData) {
			if (frontAndBackPoolText == '') {
				frontData = ObjectUtils.statObjectToArr(statDrawal.statAll[0], false, {
					op: '>',
					value: filterLevel
				});
				backData = ObjectUtils.statObjectToArr(statDrawal.statAll[1], false, {
					op: '>',
					value: filterLevel
				});
			} else {
				let arr = frontAndBackPoolText.split(',');
				frontData = arr[0].split(' ');
				backData = arr[1].split(' ');
			}
		}
		// 前后区高频分布：05-30, 02-10
		// frontData = frontData.filter(v => v >= 'N05' && v <= 'N30');
		// backData = backData.filter(v => v >= 'N02' && v <= 'N10');
		if (frontData.length == 0 || backData.length == 0) {
			console.log('getRandomNums7WithFab 过滤太多，都没号码了', filterLevel, frontData, backData);
			return [
				[],
				[]
			];
		}
		let data = [
			arrayRandom(frontData, split_index).map(v => v.slice(-2)).sort(),
			arrayRandom(backData, 2).map(v => v.slice(-2)).sort()
		];
		if (prevDrawResult) {
			let tempArr = prevDrawResult.split(' ');
			let prevDrawResultArr = [tempArr.slice(0, split_index), tempArr.slice(split_index)];
			let badCount = [
				data[0].filter(v => prevDrawResultArr[0].includes(v)).length,
				data[1].filter(v => prevDrawResultArr[1].includes(v)).length,
			];
			if (badCount[0] > 1 || badCount[1] > 1 || (badCount[0] > 0 && badCount[1] > 0)) {
				console.log('getRandomNums7WithFab 因前期号码比重超限，重新递归');
				return this.getRandomNums7WithFab(statDrawal, filterLevel, prevDrawResult, frontData, backData, frontAndBackPoolText);
			}
		}
		return data;
	}

	getRandomNums7WithCol(statDrawal, filterLevel = 1, prevDrawResult = '') {
		if (!statDrawal) {
			statDrawal = (new DltDataModel()).getDrawalStat();
		}
		let arrTemp = [],
			num = '',
			n = 10,
			pos = 0,
			data = [
				[],
				[]
			];
		for (let i = 0; i < 7; i++) {
			arrTemp = ObjectUtils.statObjectToArr(statDrawal.statColumns[i], false, {
				op: '>',
				value: filterLevel
			});
			pos = i < split_index ? 0 : 1;
			num = arrayRandom(arrTemp, 1);
			if (data[pos].includes(num)) {
				n = 10;
				while (n > 0) {
					num = arrayRandom(arrTemp, 1);
					if (!data[pos].includes(num)) {
						break;
					}
					n--;
				}
			}
			data[pos].push(num);
		}
		data[0] = data[0].sort().map(v => v.slice(-2));
		data[1] = data[1].sort().map(v => v.slice(-2));
		if (prevDrawResult) {
			let tempArr = prevDrawResult.split(' ');
			let prevDrawResultArr = [tempArr.slice(0, split_index), tempArr.slice(split_index)];
			let badCount = [
				data[0].filter(v => prevDrawResultArr[0].includes(v)).length,
				data[1].filter(v => prevDrawResultArr[1].includes(v)).length,
			];
			if (badCount[0] > 1 || badCount[1] > 1 || (badCount[0] > 0 && badCount[1] > 0)) {
				console.log('getRandomNums7WithCol 因前期号码比重超限，重新递归');
				return this.getRandomNums7WithCol(statDrawal, filterLevel, prevDrawResult);
			}
		}
		return data;
	}

	getRandomNums7WithColPart(statDrawal, filterLevel = 1, prevDrawResult = '', partKey = '') {
		if (!statDrawal) {
			statDrawal = (new DltDataModel()).getDrawalStat();
		}
		let arrTemp = [],
			num = '',
			n = 10,
			pos = 0,
			data = [
				[],
				[]
			];
		for (let i = 0; i < 7; i++) {
			pos = i < split_index ? 0 : 1;
			arrTemp = ObjectUtils.statObjectToArr(statDrawal.statColumns[i], false, {
				op: '>',
				value: filterLevel
			});
			switch (partKey) {
				case 'h1h1':
					arrTemp = arrTemp.slice(0, Math.ceil(arrTemp.length / 2));
					break;
				case 'h1h2':
					if (pos == 0) {
						arrTemp = arrTemp.slice(0, Math.ceil(arrTemp.length / 2));
					} else {
						arrTemp = arrTemp.slice(Math.ceil(arrTemp.length / 2));
					}
					break;
				case 'h2h1':
					if (pos == 0) {
						arrTemp = arrTemp.slice(Math.ceil(arrTemp.length / 2));
					} else {
						arrTemp = arrTemp.slice(0, Math.ceil(arrTemp.length / 2));
					}
					break;
				case 'h2h2':
					arrTemp = arrTemp.slice(Math.ceil(arrTemp.length / 2));
					break;
			}
			// console.log('i', i, 'pos', pos, 'partKey', partKey, arrTemp)
			num = arrayRandom(arrTemp, 1);
			if (data[pos].includes(num)) {
				n = 10;
				while (n > 0) {
					num = arrayRandom(arrTemp, 1);
					if (!data[pos].includes(num)) {
						break;
					}
					n--;
				}
			}
			data[pos].push(num);
		}
		data[0] = data[0].sort().map(v => v.slice(-2));
		data[1] = data[1].sort().map(v => v.slice(-2));
		if (prevDrawResult) {
			let tempArr = prevDrawResult.split(' ');
			let prevDrawResultArr = [tempArr.slice(0, split_index), tempArr.slice(split_index)];
			let badCount = [
				data[0].filter(v => prevDrawResultArr[0].includes(v)).length,
				data[1].filter(v => prevDrawResultArr[1].includes(v)).length,
			];
			if (badCount[0] > 1 || badCount[1] > 1 || (badCount[0] > 0 && badCount[1] > 0)) {
				console.log('getRandomNums7WithCol 因前期号码比重超限，重新递归');
				return this.getRandomNums7WithCol(statDrawal, filterLevel, prevDrawResult);
			}
		}
		return data;
	}

	/**
	 * 根据指定的号码池类型随机生成一注大乐透号码
	 * @param {Object} statDrawal 历史开奖号码统计信息 {statAll, statColumns}
	 * @param {String} poolType 号码池类型，'columns'表示按列分布随机，其他值表示按前后分区随机
	 * @param {Number} filterLevel 号码池等级，开奖次数 N 次等级，支持 1, 2, 3 等级
	 * @param {String} prevDrawResult 上期开奖号码，前区和后区都与上期号码不得重复超过1次
	 * @param {Array} frontData 前区号码数据
	 * @param {Array} backData 后区号码数据
	 * @returns {Array} 返回随机生成的大乐透号码数组，格式为[[前区号码], [后区号码]]
	 */
	getRandomNums7(statDrawal, poolType, filterLevel, prevDrawResult, frontData, backData, frontAndBackPoolText = '') {
		// console.log('getRandomNums7 参数：', {
		// 	poolType,
		// 	filterLevel,
		// 	prevDrawResult,
		// 	frontData,
		// 	backData,
		// 	frontAndBackPoolText
		// });
		if (!statDrawal) {
			statDrawal = (new DltDataModel()).getDrawalStat();
		}
		if (poolType) {
			if (poolType == 'frontAndBack') {
				return this.getRandomNums7WithFab(statDrawal, filterLevel, prevDrawResult, frontData, backData,
					frontAndBackPoolText);
			}
			if (poolType.startsWith('xcolumns-')) {
				return this.getRandomNums7WithColPart(statDrawal, filterLevel, prevDrawResult, poolType.substring(
					'xcolumns-'
						.length));
			}
		}
		return this.getRandomNums7WithCol(statDrawal, filterLevel, prevDrawResult);

	}

	/**
	 * 优选一注
	 * @param {Object} statDrawal 历史开奖号码统计信息 {statAll, statColumns}
	 * @param {Array} orderList 订单列表
	 * @param {String} poolType 号码池类型，'columns'表示按列分布随机，其他值表示按前后分区随机
	 * @param {String} prevDrawResult 上期开奖号码，前区和后区都与上期号码不得重复超过1次
	 * @returns 
	 */
	getBetterNums7(statDrawal, orderList, poolType, prevDrawResult) {
		let count = orderList.length;
		if (count == 0) {
			return [];
		}
		if (!statDrawal) {
			statDrawal = (new DltDataModel()).getDrawalStat();
		}
		let nums = [],
			list = [],
			filterLevel = 1;
		const [frontData, backData] = this.ordersToPoolData(orderList, false);
		// console.log('优选', frontData, backData)
		while (count > 0) {
			nums = this.getRandomNums7(statDrawal, poolType, filterLevel, prevDrawResult, frontData, backData);
			list.push(nums[0].join(' ') + ' ' + nums[1].join(' '));
			count--;
		}
		return list;
	}

}

export default DltOrderModel;